import java.util.HashMap;
import java.util.Map;

class Token{
	StateType type ;
	Object value;
	
	public String toString(){
		return String.valueOf(value);
	}
	public Token(StateType t, String v){
		type = t;
		if(type == StateType.INTEGER){
			try{
				value = Integer.valueOf(v);
			}catch(Exception ex10){
				try{
					value = Integer.valueOf(v.substring(2),16);
				}catch(Exception ex16){
					value = Integer.valueOf(v.substring(1),8);
				}
			}
		}else if(type == StateType.STR){
			value = v.substring(1,v.length() - 1);
		}else{
			value = v;
		}
	}
}

public final class Tokenizer {
	
	private String code = null; 
	StateMactine sm = new StateMactine();
	Tokenizer(String code){
		this.code = code;
	}
	public static Map<String, StateType> kmap = new HashMap<String, StateType>();
	static {
		kmap.put("int" , StateType.INTEGER_TYPE);
		kmap.put("float" , StateType.FLOAT_TYPE);
		kmap.put("if" , StateType.IF);
		kmap.put("else" , StateType.ELSE);
		kmap.put("while" , StateType.WHILE);
		kmap.put("break" , StateType.BREAK);
		kmap.put("print" , StateType.PRINT);
	}
	
	int index = 0;
	int row = 1;
	int col = 1;
	private Token bkt = null; 
	public Token nextToken(){
		if(bkt != null){
			Token b = bkt;
			bkt = null;
			return b;
		}
		Token t = _nextToken();
		while(t != null && t.type == StateType.SPACE){
			t = _nextToken();
		}
		return t;
	}
	public boolean hasNext(){
		return (bkt != null || (code != null && index <= code.length()));
	}

	public void putBack(Token t){
		bkt = t;
	}
	public boolean match(StateType st){
		Token t = nextToken();
		if(t == null) return false;
		if(t.type == st){
			return true;
		}else {
			putBack(t);
		}
		return false;
	}
	public Token _nextToken(){
		if(code == null){
			return null;
		}
		State last = null;
		StringBuffer sbf = new StringBuffer();
		Token ret = null;
		for(;index<code.length(); index++){
			ret = null;
			char c = code.charAt(index);
			State st = sm.nextState(c);
			if(st==null){
				if(last == null){
					System.out.println("dont accept this begin char \"" + c + "\"");
					return null;
				}
				break;
			}else if(st.getType() == StateType.DENY){
				System.out.println("------------------err-----------------------");
				System.out.println("unexpect char \"" + c + "\" \nat line : " 
						+ row + " col :" + col);
				System.out.println("------------------errend--------------------");
				ret = null;
			}else{
				if(c=='\n'){
					row++;
					col = 1;
				}else{
					col++;
				}
				sbf.append(c);
				last = st;
			}
		}
		if(last != null){
			ret =  new Token(last.getType(),  sbf.toString());
		}
		if(ret !=null && ret.type == StateType.IDENT){
			StateType st = kmap.get(ret.value);
			if(st!=null){
				ret.type = st;
			}
		}
		return ret;
	}
	/**
	 * Method main
	 *
	 *
	 * @param args
	 *
	 */  
	public static void main(String[] args) {
		String test = "342\n" + 
		"0.432\n" + 
		"453.4\n" + 
		"0x8976\n" + 
		"07476\n" + 
		"int\n" + 
		"float\n" + 
		"{}[];()\n" + 
		"dios\n" + 
		"== != <= >= =\n" + 
		"\r\n \t \n" + 
		"\"fdsfafsdfd\\\"af afdsfd\"\n" + 
		"89" ;
		
		
//		test = "Node left = null;" +
//		"left = term();" +
//		"Token t = tkn.nextToken();" +
//		"if(t==null)" +
//		"	return null;" +
//		"Node n = new Node();" +
//		"n.value = t;" +
//		"if(t.type == StateType.MINUS || t.type == StateType.PLUS){" +
//		"	n.children.add(left.parent = n);" +
//		"	n.children.add(expression().parent = n);" +
//		"}else{" +
//		"	n.children.add(term().parent = n);" +
//		"}";
//		
		test = "int a = 5.234; float b = 3;<\n"
			+ "! <= += >= !=8377243.324324 () 3244\r\n"
			+ " 432 rewrew-  \"fdsfdfds\"\n"
			+ " 09\n"
		    + "//fdafdfd 843728 fdfdfd \n"
		    + "fdfdsfd ffff";
		//test = "-3 + 04 / ( -25.9 * ( 6 - 0xf )   + 8)";
		Tokenizer tk = new Tokenizer(test);
		Token t = tk.nextToken();
		//Stack<Token> st = new Stack<Token>();
		//List<Token> l = new ArrayList<Token>();
		while(t != null){
			System.out.println(t.value + "\t\t" + t.type) ;
			t = tk.nextToken();
		}
	}	
}
